﻿using SharePoint.Security.ConfigAnalyzer.Engine;
using SharePoint.Security.ConfigAnalyzer.Engine.Common;
using SharePoint.Security.ConfigAnalyzer.Client.Models;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Security.Principal;
using System.Text;
using SharePoint.Security.DocHelpers.ExportFormats;

namespace SharePoint.Security.ConfigAnalyzer.Client.ViewModels
{
    public class RulesViewModel
    {
        public ObservableCollection<Rule> Rules { get; set; }

        public string TimeTakenForRuleExecution { get; set; }
        
        public void FetchRules()
        {
            var dataService = new Services.ActualDataService();
            var ruleSets = dataService.GetRules();
            Rules = new ObservableCollection<Rule>();

            foreach (var ruleSet in ruleSets)
            {
                foreach (var  item in ruleSet.Rules)
                {

                    var rule = new Rule();
                    rule.CurrentValue = string.Empty;
                    rule.Description = item.RuleInfo.Description ?? string.Empty;
                    rule.ExpectedValue = item.RuleInfo.ExpectedValue ?? string.Empty;
                    rule.GroupDesc = ruleSet.Description ?? string.Empty;
                    rule.GroupName = ruleSet.Title ?? string.Empty;
                    rule.Title = item.RuleInfo.Title ?? string.Empty;
                    rule.RuleObj = item;
                    rule.IsSelected = false;
                    Rules.Add(rule);
                }
            }
        }

        public void Scan()
        {
            var watch = new System.Diagnostics.Stopwatch();
            watch.Start();
            foreach (var rule in Rules.Where(c=>c.IsSelected))
            {
                try
                {
                    rule.RuleObj.Validate();
                    rule.CurrentValue = rule.RuleObj.CurrentValue;
                    rule.Status = rule.RuleObj.Status.ToString();
                }
                catch (Exception ex)
                {
                    rule.CurrentValue = string.Format("Error occurred while trying to fetch value. Error: {0}", ex.ToString());
                    rule.Status = "InConclusive";
                }
               
            }
            ObjectHelper.TimeTaken  += watch.Elapsed.Seconds;
            watch.Stop();
        }

        public string ExportToExcel()
        {
            var exporter = new ExcelExportFormat();
            return exporter.Export(CreateSummaryData(), CreateRuleDataForExport());
        }

        public IEnumerable<RuleData> CreateRuleDataForExport()
        {
            var ruleData = new List<RuleData>();

            ruleData = this.Rules.Select(c => new RuleData
            {
                Group = c.GroupName,
                CurrentVal = c.CurrentValue,
                Description = c.Description,
                ExpectedVal = c.ExpectedValue,
                Status = c.Status,
                Title = c.Title
            }).ToList();

            return ruleData;
        }

        private IEnumerable<KeyValuePair<string, string>> CreateSummaryData()
        {
            var summaryData = new List<KeyValuePair<string, string>>();

            var windowsIdentity = WindowsIdentity.GetCurrent();
            if (windowsIdentity != null)
            {
                summaryData.Add(new KeyValuePair<string, string>("Reviewed By", windowsIdentity.Name));
            }

            summaryData.Add(new KeyValuePair<string, string>("Reviewed On", DateTime.Now.ToLongDateString()));
            summaryData.Add(new KeyValuePair<string, string>("Time Taken", 
                string.Format("{0} seconds", ObjectHelper.TimeTaken)));

            summaryData.Add(new KeyValuePair<string, string>("Central Administration Site URL", BasicInformation.GetCentralAdminInfo().Url));
            var db = BasicInformation.GetContentDBInfo();
            summaryData.Add(new KeyValuePair<string, string>("Content DB Server", db.Server));
            summaryData.Add(new KeyValuePair<string, string>("Content DB Name", db.Name));

            var farms = BasicInformation.GetFarmInfo();
            summaryData.Add(new KeyValuePair<string, string>(
                string.Format("Farm Servers ({0})", farms.Count() ), 
                String.Join(Environment.NewLine,farms.ToArray())));

            var webApps = BasicInformation.GetWebAppNames().Select(c => 
                string.Format("{0}{1}", c.DisplayName == string.Empty ? "" : c.DisplayName +" ", c.Url)
            )
            .ToList();

            summaryData.Add(new KeyValuePair<string, string>(
                string.Format("Web Apps ({0})", webApps.Count), 
                String.Join(Environment.NewLine, webApps.ToArray())));
            return summaryData;
        }
    }

}
